﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using MonoTorrent.Client;
using MonoTorrent.Common;
using Uniloader.Managers;
using XamlTorrent.Managers.MonoTorrent.Properties;
using Uniloader.Interface;
using XamlTorrent.Managers.MonoTorrent.UI;
using Uniloader.Configuration;

namespace XamlTorrent.Managers.MonoTorrent
{
    public class MonoTorrentManager : TransferManager, ITaskUIFactory
    {
        public MonoTorrentManager(TransferManagerSection config) : base(config) { }

        private ClientEngine torrEngine;    // MonoTorrent client engine
        
        private DirectoryInfo torrDir;      // Temporary directory for *.torrent files
        public DirectoryInfo TorrentDirectory
        {
            get { return torrDir; }
        }

        void torrEngine_StatsUpdate(object sender, StatsUpdateEventArgs e)
        {
        }

        public override void Initialize()
        {
            // EngineSettings and TorrentSettings are 
            // serizlizable so we'll use the application 
            // settings engine to store and load them.

            #region MonoTorrent ClientEngine
            EngineSettings torrEngineSettings = Settings.Default.MonoTorrentEngineSettings;

            if (torrEngineSettings == null)
            {
                // Use default settings for the engine
                torrEngineSettings = new EngineSettings();
                Settings.Default.MonoTorrentEngineSettings = torrEngineSettings;
            }

            torrEngine = new ClientEngine(torrEngineSettings);
            torrEngine.StatsUpdate += torrEngine_StatsUpdate;
            #endregion

            // Check if we need to use default settings for torrents
            if (Settings.Default.MonoTorrentTorrentSettings == null)
                Settings.Default.MonoTorrentTorrentSettings = new TorrentSettings();

            // TorrentDirectory is where to-be-downloaded *.torrent files are stored
            string torrWorkDirPath = "";

            if (String.IsNullOrEmpty(torrWorkDirPath))
            {
                torrWorkDirPath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                    "Torrents"
                    );
            }

            torrDir = new DirectoryInfo(torrWorkDirPath);

            string savePath = Settings.Default.MonoTorrentEngineSettings.SavePath;

            if (String.IsNullOrEmpty(savePath))
                savePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

            if (!Directory.Exists(savePath))
                    Directory.CreateDirectory(savePath);
            
            // Load and register existing torrents with the engine
            LoadSuspendedTasks();
        }

        protected override int LoadSuspendedTasks()
        {
            int loaded_files = 0;

            if (torrDir.Exists)
            {
                // Grab all *.torrent files
                FileInfo[] torrFiles = torrDir.GetFiles("*.torrent");

                foreach (FileInfo torrFile in torrFiles)
                {
                    using (Stream torrFileStream = torrFile.OpenRead())
                    {
                        // Parse the file data
                        Torrent torrData = Torrent.Load(torrFileStream);

                        // Path where downloaded data for this torrent is stored
                        string torrSaveDir = Path.Combine(Settings.Default.TorrentWorkDirectory, torrData.Name);

                        // Create a manager for this torrent
                        TorrentManager torrManager = new TorrentManager(
                            torrData, torrSaveDir,
                            Settings.Default.MonoTorrentTorrentSettings
                            );

                        // Register manager with the engine and the GUI
                        torrEngine.Register(torrManager);
                        AddTask(new MonoTorrentTask(torrManager, new FileInfo("")));

                        loaded_files++;
                    }
                }
            }
            
            return loaded_files;
        }

        public override void Dispose()
        {
            torrEngine.Dispose();

            base.Dispose();
        }

        /// <summary>
        /// Writes the metadata of all stransfers to persistent storage.
        /// </summary>
        protected override void PersistTaskMetadata()
        {
            foreach (MonoTorrentTask task in this)
            {
            }
        }

        protected override void OnAddingTask(TaskEventArgs e)
        {
            MonoTorrentTask task = (MonoTorrentTask)e.Task;

            torrEngine.Register(task.TorrentManager);
        }

        protected override void OnRemovingTask(TaskEventArgs e)
        {
            MonoTorrentTask task = (MonoTorrentTask)e.Task;

            torrEngine.Unregister(task.TorrentManager);
        }

        #region ITaskUIFactory Members

        public TaskUI[] CreateNewTaskUI()
        {
            return new TaskUI[] {
                new TaskUI("Torrent", new CreateTorrentTask(this))
            };
        }

        public TaskUI CreateTaskPropertiesUI()
        {
            return new TaskUI("Torrent", new TorrentTaskProperties());
        }

        #endregion
    }
}
